package org.ncp.handler;

import org.apereo.cas.authentication.AuthenticationHandlerExecutionResult;
import org.apereo.cas.authentication.PreventedException;
import org.apereo.cas.authentication.UsernamePasswordCredential;
import org.apereo.cas.authentication.handler.support.AbstractUsernamePasswordAuthenticationHandler;
import org.apereo.cas.authentication.principal.PrincipalFactory;
import org.apereo.cas.services.ServicesManager;
import org.ncp.dto.User;
import org.ncp.util.DBConnection;
import org.ncp.util.MD5Util;
import org.ncp.util.PasswordUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;

import javax.security.auth.login.AccountException;
import java.security.GeneralSecurityException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

/**
 * 自定义验证类
 */
public class MyAuthenticationHandler extends AbstractUsernamePasswordAuthenticationHandler {
    private Integer USER_FREEZE = 2;
    private final static Logger logger = LoggerFactory.getLogger(MyAuthenticationHandler.class);
    public MyAuthenticationHandler(String name, ServicesManager servicesManager, PrincipalFactory principalFactory, Integer order) {
        super(name, servicesManager, principalFactory, order);
    }

    @Override
    protected AuthenticationHandlerExecutionResult authenticateUsernamePasswordInternal(UsernamePasswordCredential credential, String originalPassword) throws GeneralSecurityException, PreventedException {
        //1.密码MD5加密，与平台保持一致
        String passwordMD5Encode = MD5Util.MD5Encode(credential.getPassword(), "utf-8");
        String username = credential.getUsername();
        logger.info("认证用户 username = {}", username);
        System.out.println("认证用户:" + username);
        //2.查询数据库
        JdbcTemplate jdbcTemplate = new JdbcTemplate(DBConnection.getDataSource());
        String sql = "select id, username, password, salt, status from sys_user where del_flag = 0 and username = ?";
        User info = jdbcTemplate.queryForObject(sql, new Object[]{username}, new BeanPropertyRowMapper<>(User.class));
        //3.进行验证
        if (info == null) {
            logger.info("用户不存在！");
            System.out.println("用户不存在!");
            throw new AccountException("用户不存在！");
        }
        if (USER_FREEZE.equals(info.getStatus())) {
            logger.info("该用户已冻结！");
            System.out.println("该用户已冻结!");
            throw new AccountException("该用户已冻结！");
        }
        String passwordFinalEncode = PasswordUtil.encrypt(username, MD5Util.MD5Encode(passwordMD5Encode,"utf-8"), info.getSalt());
        if (!passwordFinalEncode.equals(info.getPassword())) {
            logger.info("用户名或密码错误！");
            System.out.println("用户名或密码错误！");
            throw new AccountException("用户名或密码错误！");
        }
        logger.info("用户 username = {}，认证通过！", username);
        System.out.println("用户:" + username + "，认证通过！");
        Map<String, Object> resInfo = new HashMap<>();
        resInfo.put("id", info.getId());
        resInfo.put("username", info.getUsername());
        return createHandlerResult(credential,
                this.principalFactory.createPrincipal(credential.getUsername(), resInfo),
                new ArrayList<>(0));
    }
}
